package org.qhhc.bionioaio.bio.Servier;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SwingChatServer extends JFrame {
    private int DEFAULT_PORT = 8888;
    private final String QUIT = "quit";
    private ServerSocket serverSocket;
    private Map<Integer, ClientInfo> connectedClients;
    private ExecutorService executorService;
    private boolean isRunning = false;
    
    // 客户端信息类
    private static class ClientInfo {
        Writer writer;
        String username;
        
        ClientInfo(Writer writer, String username) {
            this.writer = writer;
            this.username = username;
        }
    }
    
    // UI Components
    private JTextArea logArea;
    private JButton startButton;
    private JButton stopButton;
    private JTextField portField;
    private JLabel statusLabel;
    private JLabel clientCountLabel;
    
    public SwingChatServer() {
        // Initialize components
        this.connectedClients = new HashMap<>();
        this.executorService = Executors.newFixedThreadPool(10);
        
        // Set up the UI
        initializeUI();
    }
    
    private void initializeUI() {
        // Set window properties
        setTitle("聊天服务器");
        setSize(600, 400);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        // Create log area
        logArea = new JTextArea();
        logArea.setEditable(false);
        logArea.setLineWrap(true);
        JScrollPane scrollPane = new JScrollPane(logArea);
        
        // Create control components
        JPanel controlPanel = new JPanel(new BorderLayout());
        JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        
        JLabel portLabel = new JLabel("端口:");
        portField = new JTextField(String.valueOf(DEFAULT_PORT), 6);
        startButton = new JButton("启动服务器");
        stopButton = new JButton("停止服务器");
        stopButton.setEnabled(false);
        
        topPanel.add(portLabel);
        topPanel.add(portField);
        topPanel.add(startButton);
        topPanel.add(stopButton);
        
        JPanel statusPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        statusLabel = new JLabel("状态: 未启动");
        clientCountLabel = new JLabel("在线用户: 0");
        
        statusPanel.add(statusLabel);
        statusPanel.add(clientCountLabel);
        
        controlPanel.add(topPanel, BorderLayout.NORTH);
        controlPanel.add(statusPanel, BorderLayout.SOUTH);
        
        // Add action listeners
        startButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                startServer();
            }
        });
        
        stopButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                stopServer();
            }
        });
        
        // Add window closing listener
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                stopServer();
                executorService.shutdown();
            }
        });
        
        // Add components to frame
        getContentPane().setLayout(new BorderLayout());
        getContentPane().add(scrollPane, BorderLayout.CENTER);
        getContentPane().add(controlPanel, BorderLayout.NORTH);
    }
    
    // 开始服务器
    private void startServer() {
        if (isRunning) {
            return;
        }
        
        try {
            // Get port from UI
            int port = Integer.parseInt(portField.getText().trim());
            
            // Start server in background thread
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        isRunning = true;
                        updateUI();
                        
                        serverSocket = new ServerSocket(port);
                        log("聊天服务器已经成功启动, 端口: " + port);
                        
                        while (isRunning) {
                            try {
                                Socket socket = serverSocket.accept();
                                log("新客户端连接: " + socket.getInetAddress().getHostAddress() + ":" + socket.getPort());
                                executorService.execute(new SwingChatHandler(socket, SwingChatServer.this));
                            } catch (IOException e) {
                                if (isRunning) {
                                    log("接受客户端连接时出错: " + e.getMessage());
                                    e.printStackTrace();
                                }
                            }
                        }
                    } catch (IOException e) {
                        log("服务器启动失败: " + e.getMessage());
                        e.printStackTrace();
                        isRunning = false;
                        updateUI();
                    } finally {
                        close();
                    }
                }
            }).start();
        } catch (NumberFormatException e) {
            log("无效的端口号");
        }
    }
    
    // 停止服务器
    private void stopServer() {
        if (!isRunning) {
            return;
        }
        
        isRunning = false;
        close();
        updateUI();
        log("服务器已停止");
    }
    
    // 添加客户端
    public synchronized void addClient(Socket socket, String username) throws IOException {
        if (socket != null) {
            int key = socket.getPort();
            Writer writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            ClientInfo clientInfo = new ClientInfo(writer, username);
            connectedClients.put(key, clientInfo);
            updateClientCount();
            log("用户 " + username + " (端口: " + key + ") 已连接");
            
            // 广播新用户加入消息
            broadcastMessage("USERNAME:" + username);
        }
    }
    
    // 移除客户端
    public synchronized void removeClient(Socket socket) throws IOException {
        if (socket != null) {
            int port = socket.getPort();
            if (connectedClients.containsKey(port)) {
                ClientInfo clientInfo = connectedClients.get(port);
                clientInfo.writer.close();
                connectedClients.remove(port);
                updateClientCount();
                log("用户 " + clientInfo.username + " (端口: " + port + ") 已断开连接");
            }
        }
    }
    
    // 更新客户端数量
    private void updateClientCount() {
        final int count = connectedClients.size();
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                clientCountLabel.setText("在线用户: " + count);
            }
        });
    }
    
    // 更新UI状态
    private void updateUI() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                startButton.setEnabled(!isRunning);
                stopButton.setEnabled(isRunning);
                portField.setEnabled(!isRunning);
                statusLabel.setText("状态: " + (isRunning ? "运行中" : "已停止"));
            }
        });
    }
    
    // 广播消息给所有用户
    public synchronized void broadcastMessage(String message) throws IOException {
        for (ClientInfo clientInfo : connectedClients.values()) {
            clientInfo.writer.write(message + "\n");
            clientInfo.writer.flush();
        }
    }
    
    // 转发消息给其他用户
    public synchronized void forwardMessage(Socket socket, String msg) throws IOException {
        int senderPort = socket.getPort();
        ClientInfo senderInfo = connectedClients.get(senderPort);
        if (senderInfo != null) {
            String fwdMsg = senderInfo.username + ": " + msg;
            for (Map.Entry<Integer, ClientInfo> entry : connectedClients.entrySet()) {
                if (entry.getKey() != senderPort) {
                    entry.getValue().writer.write(fwdMsg + "\n");
                    entry.getValue().writer.flush();
                }
            }
        }
    }
    
    // 检查是否要退出
    public boolean readyToQuit(String msg) {
        return QUIT.equals(msg);
    }
    
    // 关闭服务器
    public void close() {
        if (serverSocket != null) {
            try {
                serverSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        // 关闭所有客户端连接
        for (ClientInfo clientInfo : connectedClients.values()) {
            try {
                clientInfo.writer.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        connectedClients.clear();
        updateClientCount();
    }
    
    // 记录日志
    public void log(final String message) {
        final String timestamp = new SimpleDateFormat("HH:mm:ss").format(new Date());
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                logArea.append("[" + timestamp + "] " + message + "\n");
                // 自动滚动到底部
                logArea.setCaretPosition(logArea.getDocument().getLength());
            }
        });
    }
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                SwingChatServer server = new SwingChatServer();
                server.setVisible(true);
            }
        });
    }
    
    // 聊天处理器内部类
    private class SwingChatHandler implements Runnable {
        private Socket socket;
        private SwingChatServer chatServer;
        private String username;
        
        public SwingChatHandler(Socket socket, SwingChatServer server) {
            this.socket = socket;
            this.chatServer = server;
        }
        
        @Override
        public void run() {
            try {
                BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                String msg = null;
                
                // 等待用户名
                if ((msg = reader.readLine()) != null && msg.startsWith("USERNAME:")) {
                    username = msg.substring(9);
                    chatServer.addClient(socket, username);
                }
                
                // 处理消息
                while ((msg = reader.readLine()) != null) {
                    chatServer.forwardMessage(socket, msg);
                    log("收到来自 " + username + " 的消息: " + msg);
                    
                    if (chatServer.readyToQuit(msg)) {
                        break;
                    }
                }
            } catch (IOException e) {
                log("处理客户端消息时出错: " + e.getMessage());
            } finally {
                try {
                    chatServer.removeClient(socket);
                } catch (IOException e) {
                    log("移除客户端时出错: " + e.getMessage());
                }
            }
        }
        
        private void log(String message) {
            chatServer.log(message);
        }
    }
} 